/*
 * @Author: shawnxiao
 * @Date: 2021-11-01 15:10:39
 * @LastEditTime: 2021-11-12 16:00:45
 * @FilePath: /gatt-react/src/index/views/Home/components/GattDrag/components/GattDate/components/LineAll.tsx
 */
import React, {Fragment, useRef, useState} from 'react'
import './LineAll.less'
import Slider from './Slider'
import { CheckOutlined } from '@ant-design/icons'
import {getPerColor, computedWithTime, computedGroupWidth} from '../utils'
import { timestampToTime } from '@/common/utils'

import {gattItemParams} from '../../../index'
interface PropsLineAll{
  list:gattItemParams[]
  fieldsAttr:any
  setCurrentLineDay:any
  currentDaySize:any
  rightLineX:number
  setDataArr:any
  startTime:number
  currentYear:number
  days:any[]
  setIsShowMsg:any
  setCurrentProjectMsg:any
  getMainDomRefPx:any
}

function LineAll(props:PropsLineAll) {
  const {list, fieldsAttr, rightLineX, currentDaySize, setDataArr, currentYear, startTime, days, setIsShowMsg, setCurrentProjectMsg, getMainDomRefPx} = props
  // 创建ref 数组 保存遍历组件
  const refMap:any = useRef([])
  const [isMove, setIsMove] = useState<boolean>(false)
  // 鼠标悬停展示上部日期
  // const lineMouseover = (params:any) => {
  //   console.log('params', params)
  // }
  // 鼠标按下事件拖动
  const lineMousedown = (params:any) => {
    const {e, curItem} = params
    e.stopPropagation()
    e.preventDefault()
    const cp:number = e.pageX
    let resultLeft:number = 0 // // 拖拽改变后的left
    let z = 0
    let addWidth:number = 0
    lineMouseLeave({e})
    document.onmousemove = event => {
      setIsMove(true)
      if (event.clientX >= getMainDomRefPx().w - 40) {
        const scrollX = getMainDomRefPx()?.dom?.current?.scrollLeft ? getMainDomRefPx().dom.current.scrollLeft : window.scrollX
        z = scrollX + currentDaySize.value
        // window.scrollTo(z, 0);
        getMainDomRefPx().dom.current.scrollTo({
          top: 0,
          left: z,
          behavior: 'smooth'
        })
        addWidth = event.pageX - cp
        resultLeft = curItem.left + addWidth
        refMap.current[curItem.id].style.left = resultLeft + 'px'
        if (resultLeft <= 0) {
          resultLeft = 0
        }
      } else {
        addWidth = event.pageX - cp
        resultLeft = curItem.left + addWidth
        if (resultLeft <= 0) {
          resultLeft = 0
        }
        refMap.current[curItem.id].style.left = resultLeft + 'px'
      }
      // this.lineMouseover(dom, e, id, parentId, index)
      // lineMouseLeave({e})
    }
    document.onmouseup = () => {
      // if (!resultLeft) {
      //   document.onmousemove = document.onmouseup = null
      //   return
      // }
      // 取整
      resultLeft = Math.round(resultLeft / currentDaySize.value) * currentDaySize.value
      // 根据最终生效的left值获取开始时间戳
      const startTimeStamp:number = computedWithTime({width: resultLeft, time: true, startTime, currentYear, currentDaySize}) as number
      const endTimeStamp:number = computedWithTime({width: resultLeft + curItem.widthMe, time: true, startTime, currentYear, currentDaySize}) as number
      curItem.startTime = startTimeStamp
      curItem.endTime = endTimeStamp
      curItem.left = resultLeft
      if (curItem?.popUpParams?.startTime){
        curItem.popUpParams.startTime = timestampToTime(startTimeStamp, 'second')
      }
      if (curItem?.popUpParams?.endTime){
        curItem.popUpParams.endTime = timestampToTime(endTimeStamp, 'second')
      }
      if (curItem?.parentId) {
        // 存在父级的时候 需要改变group的宽度和left
        computedGroupWidth({curItem, list, startTime, currentYear, currentDaySize})
      }
      if (Math.abs(addWidth) < currentDaySize.value){
        refMap.current[curItem.id].style.left = resultLeft + 'px'
      }
      setDataArr([...list]) // 这里赋值须注意是新的值
      document.onmousemove = document.onmouseup = null
      setIsMove(false)
    }
  }
  // 左侧拖拽增加
  /**
   * @param  {object}} curItem
   * @param  {Object} e $event
   */
  const leftCurDragMousedown = (params:any) => {
    const {e, curItem} = params
    e.stopPropagation()
    e.preventDefault()
    lineMouseLeave({e})
    const cx = e.pageX
    let resultWidthMe:number = 0 // 拖拽改变后的宽度
    let resultLeft:number = 0 // // 拖拽改变后的left
    let z = 0
    let x = 0
    let addWidth:number = 0
    let scrollToTimer:any = null
    let timers:any = null
    document.onmousemove = event => {
      setIsMove(true)
      if (
        event.clientX <= rightLineX + 80 &&
        event.pageX >= rightLineX + 80
      ) {
        if (!scrollToTimer) {
          scrollToTimer = window.setInterval(() => {
            const scrollX = getMainDomRefPx()?.dom?.current?.scrollLeft ? getMainDomRefPx().dom.current.scrollLeft : window.scrollX
            z = scrollX - currentDaySize.value
            getMainDomRefPx().dom.current.scrollTo({
              top: 0,
              left: z,
              behavior: 'smooth'
            })
            addWidth = cx - event.pageX
          }, 50)
        }
      } else if (event.clientX >= getMainDomRefPx().w - 80) {
        if (!timers) {
          timers = window.setInterval(() => {
            const scrollX = getMainDomRefPx()?.dom?.current?.scrollLeft ? getMainDomRefPx().dom.current.scrollLeft : window.scrollX
            x = scrollX + currentDaySize.value
            getMainDomRefPx().dom.current.scrollTo({
              top: 0,
              left: x,
              behavior: 'smooth'
            })
            addWidth = -(event.pageX - cx)
          }, 50)
        }
      } else {
        window.clearInterval(scrollToTimer)
        window.clearInterval(timers)
        scrollToTimer = null
        timers = null
        if (event.pageX <= rightLineX) {
          addWidth = -(rightLineX - 2 - cx)
        } else {
          addWidth = -(event.pageX - cx)
        }
      }
      resultWidthMe = curItem.widthMe + addWidth
      resultLeft = curItem.left - addWidth

      if (resultWidthMe <= currentDaySize.value) {
        resultWidthMe = currentDaySize.value
        resultLeft = curItem.left + curItem.widthMe - currentDaySize.value
      } else if (resultLeft <= 0) {
        resultLeft = 0
      }
      // 拖动更改时，slider组件需要实时更改进度宽度和指示三角形位置
      // curItem.widthChild = resultWidthMe
      // 单项数据流 => 从顶层往下的单项数据流，改变从上级传过来的数据只会对它的子组件影响，当前组件的视图更新不会更新，需要更新当前组件视图则须通过上级方法重新赋值更新上级的数据
      // setDataArr([...list])
      // 拖拽dom实时更改
      refMap.current[curItem.id].style.width = resultWidthMe + 'px'
      refMap.current[curItem.id].style.left = resultLeft + 'px'
      // this.lineMouseover(dom, e, id, parentId, index)
      // this.lineMouseleave(e, true)
    }
    document.onmouseup = events => {
      if (!resultWidthMe) {
        document.onmousemove = document.onmouseup = null
        return
      }
      window.clearInterval(scrollToTimer)
      window.clearInterval(timers)
      scrollToTimer = null
      timers = null
      // 改变的宽度和left进行取整
      resultWidthMe =
        Math.round(resultWidthMe / currentDaySize.value) *
        currentDaySize.value
      resultLeft = Math.round(parseInt(refMap.current[curItem.id].style.left, 10) / currentDaySize.value) * currentDaySize.value
      // 根据最终生效的left值获取开始时间戳
      const startTimeStamp:number = computedWithTime({width: resultLeft, time: true, startTime, currentYear, currentDaySize}) as number
      console.log( events)
      curItem.startTime = startTimeStamp
      curItem.left = resultLeft
      curItem.widthMe = resultWidthMe
      curItem.widthChild = resultWidthMe
      if (curItem?.popUpParams?.startTime){
        curItem.popUpParams.startTime = timestampToTime(startTimeStamp, 'second')
      }
      if (curItem?.parentId) {
        // 存在父级的时候 需要改变group的宽度和left
        computedGroupWidth({curItem, list, startTime, currentYear, currentDaySize})
      }
      // 拖拽dom最终生效值进行更改 => 不需要手动改dom,上级组件数据已经发生了变化会自动更新视图,但是如果拖动距离小于currentDaySize.value的时候经过上面的取整操作list数据是没有变化的但是move的时候实时更新了dom，所以需要下面的两行进行修正
      if (Math.abs(addWidth) < currentDaySize.value){
        refMap.current[curItem.id].style.width = resultWidthMe + 'px'
        refMap.current[curItem.id].style.left = resultLeft + 'px'
      }
      setDataArr([...list]) // 这里赋值须注意是新的值
      // this.checkIsin(dom, events, id, parentId, index)
      setIsMove(false)
      document.onmousemove = document.onmouseup = null
    }
  }
  const rightCurDragMousedown = (params:any) => {
    const {e, curItem} = params
    e.stopPropagation()
    e.preventDefault()
    lineMouseLeave({e})
    const cx = e.pageX
    let resultWidthMe:number = 0 // 拖拽改变后的宽度
    let z:number = 0
    let x:number = 0
    let wx:number = getMainDomRefPx()?.dom?.current?.scrollLeft ? getMainDomRefPx().dom.current.scrollLeft : window.scrollX
    let addWidth:number = 0
    let scrollToTimer:any = null
    let timers:any = null
    document.onmousemove = event => {
      setIsMove(true)
      if (event.clientX >= getMainDomRefPx().w - 80) {
        if (!scrollToTimer) {
          z = 0
          wx = getMainDomRefPx()?.dom?.current?.scrollLeft ? getMainDomRefPx().dom.current.scrollLeft : 0
          scrollToTimer = window.setInterval(() => {
            z = z + currentDaySize.value
            getMainDomRefPx().dom.current.scrollTo({
              top: 0,
              left: z + wx,
              behavior: 'smooth'
            })
            addWidth = event.pageX - cx + z
          }, 50)
        }
      } else if (event.clientX <= rightLineX + 80) {
        if (!timers) {
          timers = window.setInterval(() => {
            const scrollX = getMainDomRefPx()?.dom?.current?.scrollLeft ? getMainDomRefPx().dom.current.scrollLeft : window.scrollX
            x = scrollX - currentDaySize.value
            getMainDomRefPx().dom.current.scrollTo({
              top: 0,
              left: x,
              behavior: 'smooth'
            })
            addWidth = event.pageX - cx
          }, 50)
        }
      } else {
        window.clearInterval(scrollToTimer)
        window.clearInterval(timers)
        scrollToTimer = null
        timers = null
        addWidth = event.pageX - cx
      }
      resultWidthMe = curItem.widthMe + addWidth
      // 拖拽后超过了整体的时间跨度
      if (
        resultWidthMe + curItem.left >= days.length * currentDaySize.value
      ) {
        resultWidthMe = days.length * currentDaySize.value - curItem.left
      }
      // curItem.widthChild = resultWidthMe
      // setDataArr([...list])
      // 拖拽dom实时更改
      refMap.current[curItem.id].style.width = resultWidthMe + 'px' // 必须这样不能调换顺序
      if (resultWidthMe <= currentDaySize.value) {
        resultWidthMe = currentDaySize.value
        curItem.widthMe = resultWidthMe
        curItem.widthChild = resultWidthMe
        // setDataArr([...list])
        // 拖拽dom实时更改
        refMap.current[curItem.id].style.width = resultWidthMe + 'px'
      }
      // setDataArr([...list]) // 此处更新父级数据更新视图是为了同步三角形实时计算定位位置
      // this.lineMouseover(dom, e, id, parentId, index)
    }
    document.onmouseup = events => {
      if (!resultWidthMe) {
        document.onmousemove = document.onmouseup = null
        return
      }
      window.clearInterval(scrollToTimer)
      window.clearInterval(timers)
      scrollToTimer = null
      timers = null
      // 改变的宽度进行取整
      resultWidthMe = Math.round(resultWidthMe / currentDaySize.value) * currentDaySize.value
      const endTimeStamp:number = computedWithTime({width: curItem.left + resultWidthMe, time: true, startTime, currentYear, currentDaySize}) as number
      console.log(resultWidthMe, endTimeStamp, events)
      curItem.endTime = endTimeStamp
      curItem.widthMe = resultWidthMe
      curItem.widthChild = resultWidthMe
      if (curItem?.popUpParams?.endTime){
        curItem.popUpParams.endTime = timestampToTime(endTimeStamp, 'second')
      }
      if (curItem?.parentId) {
        // 存在父级的时候 需要改变group的宽度和endStart
        computedGroupWidth({curItem, list, startTime, currentYear, currentDaySize})
      }
      setDataArr([...list])
      // 在拖拽dom实时更改
      if (Math.abs(addWidth) < currentDaySize.value){
        refMap.current[curItem.id].style.width = resultWidthMe + 'px'
      }
      // this.checkIsin(dom, events, id, parentId, index)
      setIsMove(false)
      document.onmousemove = document.onmouseup = null
    }
  }

  const lineMouseLeave = (params:any) => {
    params.e.stopPropagation()
    params.e.preventDefault()
    // 防抖
    let timeOut:any = null // 初始化空定时器
    clearTimeout( timeOut ) // 频繁操作，一直清空先前的定时器
    timeOut = setTimeout( () => { // 只执行最后一次事件
      setIsShowMsg(false)
    }, 50 )
  }
  const lineMouseEnter = (params:any) => {
    if (isMove) return
    // 防抖
    let timeOut:any = null // 初始化空定时器
    clearTimeout( timeOut ) // 频繁操作，一直清空先前的定时器
    const gattBoxRootRight = document.getElementById('gatt-box-root-right')
    timeOut = setTimeout( () => { // 只执行最后一次事件
      todoMove()
    }, 50 )
    function todoMove () {
      let count = 0
      const showData:any[] = []
      setIsShowMsg(true)
      const curItm = {...params.item.popUpParams}
      for (const key in fieldsAttr) {
        if (curItm[key] && fieldsAttr[key].showToast){
          // 字段存在且在弹窗配置项中设置了可见
          const obj:any = {}
          count++
          obj.key = key
          obj.value = curItm[key]
          obj.label = fieldsAttr[key]?.label
          showData.push(obj)
        }
      }
      let x = params.e.clientX + 15
      let y = params.e.clientY + 15
      // 兼容横竖屏
      if (window.innerHeight >= window.innerWidth) {
        // 竖屏
        const w = gattBoxRootRight?.clientHeight ? gattBoxRootRight.clientHeight + gattBoxRootRight.offsetTop : window.innerHeight
        const contentH = count * 23 + 20
        if (x - contentH <= 0) {
          x = x - 55
        } else {
          x = x - contentH * 2 + 20
        }
        if (y + 210 >= w) {
          y = y - 210 + 50
        }
      } else {
        // 横屏
        const w = gattBoxRootRight?.clientWidth ? gattBoxRootRight.clientWidth + gattBoxRootRight.offsetLeft : window.innerWidth
        const h = gattBoxRootRight?.clientHeight ? gattBoxRootRight.clientHeight + gattBoxRootRight.offsetTop : window.innerHeight
        const contentH = count * 23 + 20
        if (x + 210 >= w) {
          x = x - 210 - 35
        }
        if (y + contentH + 35 >= h) {
          y = y - contentH - 35
        }
      }
      // 添加持续时间字段
      if (params?.item?.startTime && params?.item?.endTime){
        showData.push({
          key: 'allTime',
          label: '持续时间',
          value: `${(params.item.endTime - params.item.startTime) / (24 * 1 * 60 * 60 * 1000)}天`
        })
      }
      showData.map((item:any) => {
        item.left = x
        item.top = y
      })
      setCurrentProjectMsg([...showData])
    }
  }

  return (
    <div className="line-all">
      {
        list.length && list.map((item:gattItemParams) => {
          return item.isShow && ~~item.type === 3 ? (
            <div
              className="group"
              key={item.id + 'group'}
              id={'line' + item.id}
              style={{
                top: item.top + 'px',
                left: item.left + 'px',
                width: item.widthMe + 'px',
                backgroundColor: item?.perBgColor ? item.perBgColor : fieldsAttr?.per?.bgColor ? fieldsAttr.per.bgColor : ''
              }}
              onMouseLeave={(e:any) => lineMouseLeave({e, item})}
              onMouseEnter={(e:any) => lineMouseEnter({e, item})}
            >
              <div
                className="progress"
                style={{
                  width: item.per + '%',
                  'backgroundColor': item?.perProcessColor ? item.perProcessColor : fieldsAttr?.per?.processColors && (Object.keys(fieldsAttr.per.processColors).length) ? fieldsAttr.per.processColors[(getPerColor(Object.keys(fieldsAttr.per.processColors), item.per))] : ''
                }}
              ></div>
            </div>
          ) : item.isShow && (~~item.type === 2 || ~~item.type === 1) ? (
            <div
              className="line"
              key={item.id}
              ref={f => { refMap.current[item.id] = f }}
              style={{
                top: item.top + 'px',
                left: item.left + 'px',
                width: item.widthMe + 'px'
              }}
              // onMouseOver={(e:any) => lineMouseover({e, item})}
              onMouseDown={(e:any) => lineMousedown({e, curItem: item})}
              onMouseEnter={(e:any) => lineMouseEnter({e, item})}
              onMouseLeave={(e:any) => lineMouseLeave({e, item})}
            >
            {
              ~~item.type === 1 ? (
              <Fragment>
                <div
                  className="stoneLine"
                  style={{
                    top: -item.top + 'px',
                    height: item.top + 'px'
                  }}
                >
                </div>
                <div
                  className="milestone"
                >
                  <i className="el-icon-check">
                    <CheckOutlined />
                  </i>
                </div>
              </Fragment>
              ) : (
                <Fragment>
                  <Slider min={0} max={100} item={item} fieldsAttr={fieldsAttr} list={list} setDataArr={setDataArr} setIsShowMsg={setIsShowMsg} setIsMove={setIsMove}/>
                  <div
                    className="leftCurDrag"
                    onMouseDown={(e:any) => leftCurDragMousedown({e, curItem: item})}
                    ></div>
                  <div
                    className="rightCurDrag"
                    onMouseDown={(e:any) => rightCurDragMousedown({e, curItem: item})}
                  ></div>
                </Fragment>
              )
            }
            </div>
          ) : null
        })
      }
    </div>
  )
}

export default LineAll
